package cn.edu.nit.sys.service.impl;

import cn.edu.nit.security.UserDetailsServiceImpl;
import cn.edu.nit.sys.dto.UserDTO;
import cn.edu.nit.sys.entity.User;
import cn.edu.nit.sys.mapper.IndexMapper;
import cn.edu.nit.sys.mapper.UserMapper;
import cn.edu.nit.sys.service.IndexService;
import cn.edu.nit.sys.utils.JwtUtils;
import cn.edu.nit.sys.utils.R;
import cn.edu.nit.sys.vo.UserVO;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.QuerySendStatisticsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.QuerySendStatisticsResponse;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @Author xiaobai
 * @Date 2022/9/4 12:58
 * @Version 1.0.0
 */
@Service
@Slf4j
public class IndexServiceImpl extends ServiceImpl<IndexMapper, User> implements IndexService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Override
    public R login(UserVO userVO, HttpServletResponse response) {
        Authentication authentication = null;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(userVO.getUsername(), userVO.getPassword()));
        }catch (Exception e) {
            log.error("账号不存在：{}", e);
            return R.error("账号或密码错误");
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        Object principal = authentication.getPrincipal();
        response.addHeader("Access-Control-Expose-Headers", "token");
        response.setHeader("token", JwtUtils.generateToken(userVO.getUsername(), userVO.getOs()));
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(principal, userDTO);
        if("0".equals(userDTO.getEnable())) {
            return R.error("账号已被冻结，请联系管理员");
        }
        Map<String, ?> infoString = new HashMap<>();
        if("14".equals(userDTO.getRoleId())) {
            infoString = userMapper.selectStudentInfo(userDTO.getUsername());
        }else if("10".equals(userDTO.getRoleId())) {
            infoString = userMapper.selectTeacherInfo(userDTO.getUsername());
        }else if("1".equals(userDTO.getRoleId())){
            infoString = userMapper.adminInfo(userDTO.getUsername());
        }
        return R.ok(infoString);
    }

    @Override
    public R getPosition() {
        List<String> list = baseMapper.getPosition();
        return R.ok(list);
    }

    @Override
    public R getCount() {
        Integer studentTotal = baseMapper.studentTotal();
        Integer teacherTotal = baseMapper.teacherTotal();
        List<Map<String, Integer>> studentCount = baseMapper.studentCount();
        List<Map<String, Integer>> gradeCount = baseMapper.gradeCount();
        JSONObject map = new JSONObject();
        map.put("studentTotal", studentTotal);
        map.put("teacherTotal", teacherTotal);
        map.put("dept", studentCount);
        map.put("grade", gradeCount);
        return R.ok(map);
    }

    @Override
    public R sendPhoneCode(String phone) {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential
                .builder()
                .accessKeyId("LTAI5tCWSP1zewhkEmHQ15xh")
                .accessKeySecret("KsT3VgXRmVGrd1Ih3Gl4T941OqfUjX")
                .build());
        AsyncClient client = AsyncClient.builder()
                .region("cn-hangzhou")
                .credentialsProvider(provider)
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride("dysmsapi.aliyuncs.com")
                )
                .build();
        int num = new Random().nextInt(899999) + 100000;
        String code = "{\"code\":" + num + "}";
        try {
            SendSmsRequest sendSmsRequest = SendSmsRequest
                    .builder()
                    .phoneNumbers(phone)
                    .signName("NIT智慧校园")
                    .templateCode("SMS_460790590")
                    .templateParam(code)
                    .build();
            CompletableFuture<SendSmsResponse> sendResponse = client.sendSms(sendSmsRequest);
            SendSmsResponse sendResp = sendResponse.get();
            String jsonStr = new Gson().toJson(sendResp);
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
            String body = jsonObject.get("body").toString();
            String rsCode = JSONObject.parseObject(body).get("code").toString();
            log.info("短信发送结果：{}", new Gson().toJson(sendResp));
            log.info("body：{}", body);
            log.info("code：{}", rsCode);
            // 发送成功 ===> 缓存验证码
            // 验证码有效期 ---> 5分钟
            if("OK".equals(rsCode)) {
                redisTemplate.opsForValue().set(phone, Integer.toString(num), 2, TimeUnit.MINUTES);
                return R.ok("验证码发送成功");
            }else {
                return R.error("验证码发送失败");
            }
        } catch (InterruptedException e) {
            log.error("错误：{}", e);
            return R.sys_error();
        } catch (ExecutionException e) {
            log.error("错误：{}", e);
            return R.sys_error();
        }
    }

    @Override
    public R verifyCode(Map<String, String> params) {
        String phone = params.get("phone");
        String code = params.get("code");
        String codeStr = redisTemplate.opsForValue().get(phone);
        if(code.equals(codeStr)) {
            // 验证通过移除验证码缓存
            redisTemplate.opsForValue().set(phone, "", 5, TimeUnit.MILLISECONDS);
            return R.ok("");
        }
        return R.error("验证码错误");
    }
}
